#pragma once

#include "common.h"
#include "singleTon.h"

class Packet;

class Register
{
public:

	Register(){}
	virtual ~Register(){}
};

class RegHandler
{
public:
	
	virtual int Execute(Register *reg, Packet& pck)  = 0;
	virtual ~RegHandler() {};
};

template <typename Class, typename Param>
class RegHandlerT : public RegHandler
{
	typedef int (Class::*Method)(Param&);

public:

	RegHandlerT(Method fun): _function(fun) {}
	virtual ~RegHandlerT() {};

	virtual int Execute(Register *reg, Packet& pck)
	{
		Class *object = dynamic_cast<Class*>(reg);
		if (object == NULL)
			return -1;

		Param& param = dynamic_cast<Param&>(pck);
		(object->*_function)(param);

		return 0;
	}

private:

	Method _function;
};

class HandlerMap
{
	friend class SingleTon<HandlerMap>;

public:

	typedef std::map<uint16, RegHandler*> HandlerMapType;

	template <typename Class, typename Param>
	void RegisterHandler(uint16 opcode, int(Class::*fun)(Param&))
	{
		ASSERT(_handlers.count(opcode) == 0);
		RegHandler* hander = SAFE_NEW RegHandlerT<Class, Param>(fun);
		_handlers[opcode] = hander;
	}

	void ClearHandlers()
	{
		for (HandlerMapType::iterator it = _handlers.begin(); it != _handlers.end(); it ++)
			SAFE_DELETE(it->second);
	}
	
	HandlerMapType& GetMap() {  return _handlers; }

private:

	HandlerMapType	_handlers;
};

#define sHanlder					 SingleTon<HandlerMap>::Instance()
#define sHanlderMap					 sHanlder.GetMap()
#define REG_HANDLER(opcode, handler) sHanlder.RegisterHandler(opcode, handler)
#define UNREG_HANDLERS()			 sHanlder.ClearHandlers() 